/*
 * XbEvent.cpp
 *
 *  Created on: Dec 31, 2009
 *      Author: evaleto
 */

#include "config.h"
#include <WProgram.h>
#include <math.h>
#include "XbEvent.h"
#include "Led.h"
#include "XbLiteReader.h"
#include "Online.h"

// online helper
#ifdef CONFIG_WITH_ETHERNET
Online online=Online();
#endif

XbEvent::XbEvent() {
	time=millis();
	pulses=0;
	power=0;
	bufferpowersize=buffertype=0;
}

XbEvent::~XbEvent() {
}

/**
 * compute power from pulses and time
 */
uint16_t XbEvent::computePower(uint32_t pulses, uint32_t intime){
	// get time for one pulse (in millis)
	double time=double(intime/pulses);
	// (450ws * 1000) / millis
	return (uint16_t) lround((450000.0)/(time));
}

uint16_t XbEvent::logpower(uint32_t ms){
	power=computePower(pulses,(ms-time));
	time=millis();
	pulses=0;
	return power;
}

/**
 *
 */
uint16_t XbEvent::avg(uint16_t buffer[], uint8_t len){
	uint16_t power=0;for (uint8_t i=0;i<(len);i++ )
		power+=buffer[i];
	return power/len; // average

}

/**
 *
 */
bool XbEvent::managecache(uint8_t slice, uint8_t max, uint32_t ms){
	bufferpower[bufferpowersize++]=logpower(ms);
#ifdef CONFIG_WITH_ETHERNET
	if(online.update(buffertype,bufferpower,bufferpowersize)){
		bufferpowersize=0;
		buffertype=SEC;
		return true;
	}
#endif
	if (bufferpowersize>=max){
		bufferpowersize=0;
		for (uint8_t page=0;page<max;page+=slice)
			bufferpower[bufferpowersize++]=avg(&bufferpower[page],slice);

		buffertype=(buffertype+1)%(DAY+1); //SEC --> MIN --> HOUR --> DAY --> SEC
	}
	return false;

}

void XbEvent::onReceiveData(XbLiteReader &xb){

	uint32_t ms=millis();
	pulses++;
	// compute power each >5 seconds
	// update online power
	// bufferise power until min
	if((ms-time)>=SEC_ELAPSED && buffertype == SEC){
		// each slice of 15[5s] == 1 min with max 4 min
		if(managecache(15,60,ms))return;
	}

	// compute power hour each >60 seconds
	if ((ms-time)>MIN_ELAPSED && buffertype == MIN){
		// each slice of 60[min] == 1 hour with max of 1 hour
		if(managecache(60,60,ms))return;
	}

	// compute power hour each >3600 seconds
	if ((ms-time)>HOUR_ELAPSED && buffertype == HOUR){
		// each slice of 24[hour] == 1 day with max of 2 days
		if(managecache(24,48,ms))return;
	}

	// compute power hour each >3600*24 seconds
	if ((ms-time)>DAY_ELAPSED && buffertype == DAY){
		// each slice of 1[day] == 1 day with max of 60 days
		if(managecache(1,60,ms))return;
	}


#ifdef CONFIG_WITH_DEBUG
	Serial.print("current power :" );Serial.print(power );Serial.println(" [w]");
//	if(bufferpowersize){
//		switch (buffertype){
//		case SEC:
//			Serial.print("buffer [" );
//			Serial.print(bufferpowersize*5,DEC );
//			Serial.println("]seconds" );
//			break;
//		case MIN:
//			Serial.print("buffer [" );
//			Serial.print(bufferpowersize,DEC );
//			Serial.println("]minutes" );
//			break;
//		case HOUR:
//			Serial.print("buffer [" );
//			Serial.print(bufferpowersize,DEC );
//			Serial.print("]hours " );
//			break;
//		default:
//			break;
//		}
//	}

#endif



	Led::flash(CONFIG_LEDPULSE);
}

void XbEvent::onError(XbLiteReader &xb){
//	Led::flash(CONFIG_LEDERROR);
#ifdef CONFIG_WITH_DEBUG2
		Serial.print("error, appid: ");
		Serial.print(xb.app_id,HEX);
		Serial.print(", ");
#endif
}
